# [USACO18JAN] Cow at Large G
题意:
给定一个迷宫,构成一棵有根树,你开始在根节点,出口是每个叶子节点, 可以在每个出口放一个守卫,每 1个 单位时间内,你和守卫都可以移动到相邻的一个点,如果某一时刻 守卫与你相遇了(在边上或点上均算),则你将被抓住。问为了保证抓住你, 最少需要几个守卫。
解法:
在你屁股后面追的永远都追不上你,所以只用考虑往前走,对于一个节点  ,如果这个在  的子树中中距离  最近的叶子节点,能在我们到达之前到达,那么我们肯定不会往这个节点走,相当于一个守卫守住了一棵子树。按照这个思想两边  就做啦。
Code
| #include <iostream> | |
| #include <algorithm> | |
| #include <cstring> | |
| #include <cstdio> | |
| #include <cmath> | |
| #include <map> | |
| #include <queue> | |
| #include <stack> | |
| #include <set> | |
| #include <iomanip> | |
| using namespace std; | |
| const int MAXN=1e6+10; | |
| struct edge{ | |
| int nex,to; | |
| }p[MAXN]; | |
| vector<int> qtree; | |
| int cnt,head[MAXN],dep[MAXN],dis[MAXN],ans; | |
| void add(int from,int to){ | |
| p[++cnt]=edge{head[from],to}; | |
| head[from]=cnt; | |
| } | |
| void dfs(int now,int fa){ | |
| dep[now]=dep[fa]+1; | |
| bool fla=false; | |
| for(int i=head[now];i;i=p[i].nex){ | |
| int to=p[i].to; | |
| if(to==fa){ | |
| continue; | |
|         } | |
| dfs(to,now); | |
| fla=true; | |
| if(dis[now]==0){ | |
| dis[now]=dis[to]+1; | |
| }else{ | |
| dis[now]=min(dis[to]+1,dis[now]); | |
|         } | |
|     } | |
| if(!fla){ | |
| qtree.push_back(now); | |
|     } | |
| } | |
| void dfs2(int now,int fa){ | |
| for(int i=head[now];i;i=p[i].nex){ | |
| int to=p[i].to; | |
| if (to==fa){ | |
| continue; | |
|         } | |
| if(dep[to]-1>=dis[to]){ | |
| ans++; | |
| }else{ | |
| dfs2(to,now); | |
|         } | |
|     } | |
| } | |
| int main(){ | |
| int n,m; | |
| cin>>n>>m; | |
| for(int i=1;i<n;i++){ | |
| int x,y; | |
| cin>>x>>y; | |
| add(x,y); | |
| add(y,x); | |
|     } | |
| dfs(m,0); | |
| dfs2(m,0); | |
| cout<<ans; | |
| } | 
